package com.dhcc.bpm.alarm.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dhcc.bpm.alarm.config.*;
import com.dhcc.bpm.alarm.entity.*;
import com.dhcc.bpm.alarm.mapper.AlarmRecordMapper;
import com.dhcc.bpm.alarm.service.IAlarmObjGroupService;
import com.dhcc.bpm.alarm.service.IAlarmObjectGroupService;
import com.dhcc.bpm.alarm.service.IAlarmObjectService;
import com.dhcc.bpm.alarm.service.IAlarmRecordService;
import com.dhcc.bpm.alarm.utils.BaseUtils;
import com.dhcc.bpm.alarm.vo.AlarmRecordVO;
import com.dhcc.bpm.common.segmentId.LocalCacheIdGenerator;
import com.dhcc.bpm.common.utils.SendSMSUtils;
import com.dhcc.bpm.modules.mail.service.MailService;
import com.dhcc.bpm.modules.system.service.IDictService;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.tool.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xiafayu
 * @since 2022-02-16
 */
@Slf4j
@Service("recordServiceImpl1")
public class AlarmRecordServiceImpl extends ServiceImpl<AlarmRecordMapper, AlarmRecord> implements IAlarmRecordService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private LocalCacheIdGenerator localCacheIdGenerator;
    @Autowired
    private SendSMSUtils sendSMSUtils;
    @Autowired
    private MailService mailService;
    @Autowired
    private IAlarmObjectService alarmObjectService;
    @Autowired
    private IAlarmObjectGroupService alarmObjectGroupService;
    @Autowired
    private IAlarmObjGroupService alarmObjGroupService;
    @Autowired
    private IDictService dictService;

    private ThreadLocalRandom random = ThreadLocalRandom.current();
    @Override
    public IPage<AlarmRecordVO> selectAlarmRecordPage(IPage<AlarmRecordVO> page, AlarmRecordVO alarmRecord) {
        return page.setRecords(baseMapper.selectAlarmRecordPage(page, alarmRecord));
    }

    @Override
    public boolean insertAlarmRecord(AlarmRecord alarmRecord,AlarmStrategy alarmStrategy, AlarmNotice alarmNotice, String msg,String noticeContent,Object infoConfig) {
        //在插入前执行告警通知
       if(alarmRecord==null) {
           alarmRecord = new AlarmRecord();
           alarmRecord.setSystemno(alarmStrategy.getSystemno());
           alarmRecord.setSystemname(alarmStrategy.getSystemname());
           alarmRecord.setStrategyName(alarmStrategy.getStrategyName());
           alarmRecord.setStrategyCode(alarmStrategy.getStrategyCode());
           alarmRecord.setStrategyType(alarmStrategy.getStrategyType());
           alarmRecord.setTxCode(alarmNotice.getTxCode());
           alarmRecord.setTxDesc(alarmNotice.getTxDesc());
           alarmRecord.setRuleDesc(alarmStrategy.getRuleDesc());
           alarmRecord.setNoticeName(alarmNotice.getNoticeName());
           alarmRecord.setNoticeCode(alarmNotice.getNoticeCode());
           alarmRecord.setTriggerMethod(alarmStrategy.getTriggerMethod());
           alarmRecord.setNoticeMethod(alarmNotice.getNoticeMethod());
           alarmRecord.setAlarmTime(BaseUtils.getSystemDateStringY2NO());
           if("01".equals(noticeContent)){
               alarmRecord.setAlarmMessage(msg);
           }else {
               alarmRecord.setAlarmMessage(makeContentMould(alarmNotice, alarmStrategy, alarmRecord, msg,infoConfig));
           }
           alarmRecord.setDealStatus("02");
       }
       if("01".equals(alarmNotice.getNoticeType())){
               //单个对象告警，直接查
           AlarmObject alarmObject = alarmObjectService.getOne(new QueryWrapper<AlarmObject>().eq("OBJECTNO",alarmNotice.getNoticeObjno()).eq("IENABLE","1"));
           if(alarmObject==null){
               alarmObject = new AlarmObject();
               alarmObject.setObjectno(alarmNotice.getNoticeObjno());
               noticeObject(alarmObject,alarmNotice,alarmRecord,false);
           }else {
               noticeObject(alarmObject,alarmNotice,alarmRecord,true);
           }
       }else {
           //如果是群组，先去redis 查对应的alarmObject Id,再查数据
           AlarmObjGroup alarmObjGroup = alarmObjGroupService.getOne(new QueryWrapper<AlarmObjGroup>().eq("OBJ_GROUP_NO",alarmNotice.getNoticeObjno()));
           List<AlarmObjectGroup> alarmObjectGroupList = alarmObjectGroupService.list(new QueryWrapper<AlarmObjectGroup>().eq("GROUP_ID",alarmObjGroup.getId()));
           if(alarmObjectGroupList.isEmpty()){
               log.error("群组下没有通知对象，不进行通知");
           }else {
               for (AlarmObjectGroup o: alarmObjectGroupList) {
                   Object object = redisUtil.get(RedisKey.ALARM_OBJECT_KEY+o.getObjectId()+"");
                   if(object==null){
                       AlarmObject alarmObject = alarmObjectService.getOne(new QueryWrapper<AlarmObject>().eq("ID",o.getObjectId()).eq("IENABLE","1"));
                      if(alarmObject==null){
                          alarmObject = new AlarmObject();
                          alarmObject.setId(o.getObjectId());
                          noticeObject(alarmObject,alarmNotice,alarmRecord,false);
                      }else {
                          //随机缓存，防止缓存雪崩
                          redisUtil.set(RedisKey.ALARM_OBJECT_KEY+alarmObject.getId(),alarmObject,random.nextInt(60*60*12,60*60*24));
                          noticeObject((AlarmObject) object,alarmNotice,alarmRecord,true);
                      }
                   }else {
                       noticeObject((AlarmObject) object,alarmNotice,alarmRecord,true);
                   }
               }
           }
       }
        return baseMapper.insert(alarmRecord) > 0;
    }
    private String makeContentMould(AlarmNotice alarmNotice,AlarmStrategy alarmStrategy,AlarmRecord alarmRecord,String msg,Object infoConfig){
        //获取执行方式
        String infoConfigStr="";
        String thresholdRule="";
        if(alarmStrategy.getAlarmContentMould().contains("${infoConfig}")){
            if("01".equals(alarmStrategy.getExecMethod())){
                AlarmFtpInfoConfig alarmFtpInfoConfig = (AlarmFtpInfoConfig) infoConfig;
                infoConfigStr="服务器IP："+alarmFtpInfoConfig.getFtpIp()+","+"服务器用户："+alarmFtpInfoConfig.getFtpUser();
            }else if("02".equals(alarmStrategy.getExecMethod())){
                AlarmDbInfoConfig alarmDbInfoConfig = (AlarmDbInfoConfig) infoConfig;
                infoConfigStr="数据库类型："+alarmDbInfoConfig.getDbtype()+",数据库IP："+alarmDbInfoConfig.getDbIp()+",用户："+alarmDbInfoConfig.getDbUser()+",实例名："+alarmDbInfoConfig.getDbInstance();
            }
        }

        if("01".equals(alarmStrategy.getContentType())){
            msg = dictService.getValue("policy_type",alarmStrategy.getStrategyType())+"：告警阈值为"+msg;
            thresholdRule = alarmStrategy.getAlarmTerm()+alarmStrategy.getAlarmThreshold();
        }

        return alarmStrategy.getAlarmContentMould().replace("${msg}",msg).replace("${execMethod}", ExecMethod.getValue(alarmStrategy.getExecMethod())).replace("${alarmTime}",BaseUtils.getSystemDateOfString())
                .replace("${infoConfig}",infoConfigStr).replace("${thresholdRule}",thresholdRule)
                .replace("${removeMethod}", RemoveMethod.getValue(alarmStrategy.getRemoveMethod())).replace("${systemname}",alarmNotice.getSystemname())
                .replace("${systemnno}",alarmNotice.getSystemno()).replace("${strategyName}",alarmStrategy.getStrategyName())
                .replace("${noticeName}",alarmNotice.getNoticeName()).replace("${exceptionLevel}", ExceptionLevel.getValue(alarmNotice.getExceptionLevel())).replace("${txRisk}", StringUtils.isBlank(alarmStrategy.getTxRisk())?"":alarmStrategy.getTxRisk())
                .replace("${alarmEnv}", AlarmEnvMethod.getValue(alarmNotice.getAlarmEnv()));
    }
    private void  noticeObject(AlarmObject object,AlarmNotice alarmNotice,AlarmRecord alarmRecord,boolean flag){

        //短信
        alarmRecord.setAlarmTranno(localCacheIdGenerator.nextId());
        if(!flag){
            alarmRecord.setNoticeStatus("01");
            if(!StringUtils.isBlank(alarmNotice.getNoticeObjno())){
                alarmRecord.setAlarmReason("告警对象不存在,对象编号为"+alarmNotice.getNoticeObjno());
            }else {
                alarmRecord.setAlarmReason("告警对象不存在,对象ID为"+alarmNotice.getNoticeObjno());
            }
            alarmRecord.setObjectName("佚名!!!");
        }else {
            log.info("对告警信息进行通知,通知方式{}",NoticeMethod.getValue(alarmNotice.getNoticeMethod()));
            alarmRecord.setObjectName(object.getObjectname());
            alarmRecord.setAlarmMessage(alarmRecord.getAlarmMessage().replace("${objectname}",object.getObjectname()));
            try {
                if("01".equals(alarmNotice.getNoticeMethod())){
                    log.info("短信通知，通知内容{}",alarmRecord.getAlarmMessage());
                    sendSMSUtils.sendSMS(object.getContactinfo(),alarmRecord.getAlarmMessage());
                }
                //微信
                if("02".equals(alarmNotice.getNoticeMethod())){
                    log.info("微信通知，通知内容{}",alarmRecord.getAlarmMessage());
                }
                //邮件通知
                if("03".equals(alarmNotice.getNoticeMethod())){
                    log.info("邮件通知，通知内容{}",alarmRecord.getAlarmMessage());
                    mailService.sendSimpleMail(object.getEmail(),alarmNotice.getNoticeName(),alarmRecord.getAlarmMessage());
                }
                //API
                if("04".equals(alarmNotice.getNoticeMethod())){
                    log.info("API通知，通知内容{}",alarmRecord.getAlarmMessage());
                    HttpResponse<String> response = Unirest.post(object.getContactinfo())
                            .header("Content-Type", "application/json")
                            .body(JSON.toJSONString(alarmRecord))
                            .asString();
                    if(response.getStatus()!=200){
                        throw new Exception(response.getBody());
                    }
                }
                //H5
                if("05".equals(alarmNotice.getNoticeMethod())){
                    log.info("H5通知，通知内容{}",alarmRecord.getAlarmMessage());
                    HttpResponse<String> response = Unirest.post(object.getContactinfo())
                            .header("Content-Type", "application/json")
                            .body(JSON.toJSONString(alarmRecord))
                            .asString();
                    if(response.getStatus()!=200){
                        throw new Exception(response.getBody());
                    }
                }
                //企业微信
                if("06".equals(alarmNotice.getNoticeMethod())){
                    log.info("企业微信通知，通知内容{}",alarmRecord.getAlarmMessage());
                    JSONObject data = new JSONObject();
                    data.put("msgtype","text");
                    JSONObject text = new JSONObject();
                    text.put("content",alarmRecord.getAlarmMessage().replace("${user}",object.getContactinfo()));
                    text.put("mentioned_mobile_list","all");
                    data.put("text",text);
                    HttpResponse<String> response = Unirest.post(object.getContactinfo())
                            .header("Content-Type", "application/json")
                            .body(data.toJSONString())
                            .asString();
                    if(response.getStatus()!=200){
                        throw new Exception(response.getBody());
                    }
                }
                alarmRecord.setNoticeStatus("00");
                alarmRecord.setNoticeTimes(BigDecimal.ONE);
            } catch (Exception e) {
                alarmRecord.setNoticeStatus("01");
                alarmRecord.setAlarmReason(e.getMessage());
            }
        }

    }
}
